import datetime
import json
import logging
import re
import uuid
from decimal import Decimal
from hashlib import md5

from qcloud_cos import CosConfig, CosS3Client
from sqlalchemy import and_, desc, extract, func

from base.connection import redis_util
from base.request import ApiBaseHandler
from common.definition import (
    AgencyType,
    OrderStatus,
    OrderType,
    PayStatus,
    PayType,
    ret_msg,
)
from common.printer import printOrder
from conf import config
from conf.config import DOMAIN
from daemon import tasks
from helper.api_helper import ApiHelper
from helper.beanstalkd import add_mq_task
from helper.payment.pay_util import generator_trade_no
from helper.payment.refund import cancel_order_immediate_refund
from helper.user import UserHelper

logger = logging.getLogger("wechat.handlers.api.admin")


class Order(ApiBaseHandler):
    async def get(self):
        open_id = await self.get_open_id()
        order_status = int(self.get_parameter("t", 0))
        date = self.get_parameter("date", None)
        order_id = self.get_parameter("order_id", None)
        page_index = int(self.get_parameter("page_index", 0))
        page_size = int(self.get_parameter("page_size", 10))
        ApiHelper.inspect_common_params(page_index, page_size)
        page_start = page_index * page_size
        agency_id, store_id = self.store_agency_id(open_id)
        agency_uid = self.get_agency_uid(open_id)
        supplier_id = UserHelper.get_supplier_id(agency_uid)
        is_supplier = UserHelper.is_supplier_staff(agency_uid)

        class Benefit(object):
            pass

        class GoodsOrder(object):
            pass

        class UserAddress(object):
            pass

        class User(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "sdet_benefit", "model": Benefit},
                {"db_table": "sdet_address", "model": UserAddress},
                {"db_table": "sdet_order", "model": GoodsOrder},
                {"db_table": "ebt_user", "model": User},
            ]
        )

        filters = dict(
            sdef_order_is_delete=0,
            sdef_order_factory_uid=config.FACTORY_UID,
        )

        if is_supplier and supplier_id:
            # 供应商
            filters["sdef_order_supplier_id"] = supplier_id
        elif store_id:
            # 门店
            filters["sdef_order_store_id"] = store_id
        else:
            # 合伙人
            filters["sdef_order_device_id"] = open_id

        # 63133 = 6已退款 31审核中 33售后中 （退款/售后）
        if order_status and order_status != 63133:
            filters["sdef_order_status"] = order_status

        # 限制店员只能查看扫自己码下的单
        # if agency_id == store_id:
        #     flag = True
        # else:
        #     flag = False
        # if not flag:
        #     filters["sdef_order_describe"] = open_id

        if date:
            date = date.replace(" ", "")
            now = datetime.datetime.now()
            if date == "two" or date == "2":
                date_start = (now + datetime.timedelta(days=-1)).replace(
                    hour=0, minute=0, second=0
                )
                date_end = now
            elif date == "7":
                date_start = (now + datetime.timedelta(days=-6)).replace(
                    hour=0, minute=0, second=0
                )
                date_end = now
            elif date == "30":
                date_start = (now + datetime.timedelta(days=-29)).replace(
                    hour=0, minute=0, second=0
                )
                date_end = now
            else:
                date_list = date.split("-")
                if len(date_list) == 3:
                    year, month, day = (
                        int(date_list[0]),
                        int(date_list[1]),
                        int(date_list[2]),
                    )
                    date_start = datetime.datetime(year, month, day).replace(
                        hour=0, minute=0, second=0
                    )
                    date_end = datetime.datetime(year, month, day).replace(
                        hour=23, minute=59, second=59
                    )
                elif len(date_list) == 6:
                    y1, m1, d1 = int(date_list[0]), int(date_list[1]), int(date_list[2])
                    y2, m2, d2 = int(date_list[3]), int(date_list[4]), int(date_list[5])
                    date_start = datetime.datetime(y1, m1, d1).replace(
                        hour=0, minute=0, second=0
                    )
                    date_end = datetime.datetime(y2, m2, d2).replace(
                        hour=23, minute=59, second=59
                    )
                else:
                    session.close()
                    return self.write(ret_msg(code=-1, error_message="请求参数错误！"))

            order_list = (
                session.query(GoodsOrder)
                .filter_by(**filters)
                .filter(GoodsOrder.sdef_order_pay_status.in_([1, 2]))
                .filter(GoodsOrder.sdef_order_create_time >= date_start)
                .filter(GoodsOrder.sdef_order_create_time <= date_end)
                .order_by(GoodsOrder.sdef_order_id.desc())[
                    page_start : page_start + page_size
                ]
            )
        elif order_id:
            filters["sdef_order_id"] = order_id
            order_list = (
                session.query(GoodsOrder)
                .filter_by(**filters)
                .filter(GoodsOrder.sdef_order_pay_status.in_([1, 2]))
                .order_by(GoodsOrder.sdef_order_id.desc())
                .all()
            )
        elif order_status == 63133:  # 63133 = 6已退款 31审核中 33售后中 （退款/售后）
            order_list = (
                session.query(GoodsOrder)
                .filter_by(**filters)
                .filter(GoodsOrder.sdef_order_pay_status.in_([1, 2]))
                .filter(GoodsOrder.sdef_order_status.in_([6, 31, 33]))
                .order_by(GoodsOrder.sdef_order_id.desc())[
                    page_start : page_start + page_size
                ]
            )
        else:
            order_list = (
                session.query(GoodsOrder)
                .filter_by(**filters)
                .filter(GoodsOrder.sdef_order_pay_status.in_([1, 2]))
                .order_by(GoodsOrder.sdef_order_id.desc())[
                    page_start : page_start + page_size
                ]
            )

        order_array = []
        for o in order_list:
            status_code = o.sdef_order_status
            order_id = o.sdef_order_id
            benefit = (
                session.query(func.sum(Benefit.fee))
                .filter_by(agency_uid=agency_uid, is_valid=1, order_id=order_id)
                .scalar()
            )

            if o.sdef_order_pay_status == PayStatus.REFUND:
                status_code = OrderStatus.REFUND
                o.sdef_order_status = OrderStatus.REFUND

            ship_type = o.sdef_order_ship_type
            address_info = {}
            if ship_type in [0, 3]:
                address_id = o.sdef_order_address_id
                address = (
                    session.query(UserAddress)
                    .filter_by(sdef_address_id=address_id)
                    .first()
                )
                address_info = (
                    dict(
                        name=address.sdef_address_name,
                        phone=address.sdef_address_phone,
                        province=address.sdef_address_province,
                        city=address.sdef_address_city,
                        county=address.sdef_address_county,
                        detail=address.sdef_address_detail,
                    )
                    if address
                    else {}
                )
            cart_goods = json.loads(o.sdef_order_goods)
            goods_total_fee = 0
            for c in cart_goods:
                goods_total_fee += Decimal(c["goods_price"]) * Decimal(c["count"])

            if o.sdef_order_type == OrderType.PINGUI:
                service_fee = ApiHelper.service_fee(goods_total_fee)
            else:
                service_fee = Decimal(0)
            delivery_fee = o.sdef_order_delivery_fee
            delivery_fee = Decimal(delivery_fee) if delivery_fee else Decimal(0)

            user_id = o.sdef_order_device_id
            user = session.query(User).filter_by(ebf_user_id=user_id).first()
            nick_name = user.ebf_user_nickname

            order_array.append(
                dict(
                    order_id=order_id,
                    nick_name=nick_name,
                    ship_type=ship_type,
                    address_info=address_info,
                    status_code=status_code,
                    cart_goods=cart_goods,
                    price_total="%.2f"
                    % (
                        o.sdef_order_fee
                        + o.sdef_order_balance_fee
                        + o.sdef_order_coupon_fee
                    ),
                    order_fee="%.2f" % o.sdef_order_fee,
                    balance_fee="%.2f" % o.sdef_order_balance_fee,
                    coupon_fee="%.2f" % o.sdef_order_coupon_fee,
                    goods_total_fee="%.2f" % goods_total_fee,
                    service_fee="%.2f" % service_fee,
                    delivery_fee="%.2f" % delivery_fee,
                    pay_type=o.sdef_order_pay_type,
                    order_type=o.sdef_order_type,
                    room_id=o.sdef_order_room_id,
                    store_id=o.sdef_order_store_id,
                    benefit_fee="%.2f" % benefit if benefit else "0.00",
                    create_time=o.sdef_order_create_time.strftime("%m-%d %H:%M:%S"),
                    message=o.sdef_order_message,
                    pay_time=o.sdef_order_pay_time.strftime("%m-%d %H:%M:%S")
                    if o.sdef_order_pay_time
                    else None,
                    express_info=o.sdef_order_express_no,
                )
            )

        session.commit()
        session.close()
        return self.finish(ret_msg(data=order_array))

    async def post(self):
        open_id = await self.get_open_id()
        order_id = self.get_parameter("order_id", None)
        action = self.get_parameter("action", None)
        courier = self.get_parameter("courier", None)
        courier_number = self.get_parameter("courier_number", "")
        remarks = self.get_parameter("remarks", None)
        agency_id, store_id = self.store_agency_id(open_id)
        agency_uid = self.get_agency_uid(open_id)
        supplier_id = UserHelper.get_supplier_id(agency_uid)
        is_supplier = UserHelper.is_supplier_staff(agency_uid)

        if not order_id:
            return self.write(ret_msg(code=-1, error_message="请求参数缺少订单号！"))

        filters = dict(
            sdef_order_id=order_id,
            sdef_order_is_delete=0,
            sdef_order_factory_uid=config.FACTORY_UID,
            sdef_order_type=OrderType.NORMAL,
            sdef_order_pay_status=PayStatus.SUCCESS,
        )

        if supplier_id and is_supplier:
            filters["sdef_order_supplier_id"] = supplier_id
        elif store_id:
            filters["sdef_order_store_id"] = store_id
        else:
            return self.write(ret_msg(code=-1, error_message="商家或店员账号错误！"))

        # 是否店主（总账号）
        if agency_id == store_id:
            flag = True
        else:
            flag = False

        # 限制店员只能查看扫自己码下的单
        # if not flag:
        #     filters["sdef_order_describe"] = open_id

        class GoodsOrder(object):
            pass

        class Agency(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "sdet_order", "model": GoodsOrder},
                {"db_table": "ebt_agency", "model": Agency},
            ]
        )

        order = session.query(GoodsOrder).filter_by(**filters).first()
        if not order:
            session.close()
            return self.write(ret_msg(code=-1, error_message="订单不存在！"))

        if action == "receive":
            # 店内消费/自提
            if order.sdef_order_status != OrderStatus.WAIT_EXPRESS:
                session.close()
                return self.write(ret_msg(code=-1, error_message="已经接单，请刷新页面！"))

            order.sdef_order_status = OrderStatus.EXPRESSED
            session.commit()
        elif action == "ship":
            # 快递/物流配送
            if order.sdef_order_status != OrderStatus.WAIT_EXPRESS:
                session.close()
                return self.write(ret_msg(code=-1, error_message="非待发货订单，请刷新页面！"))

            order.sdef_order_status = OrderStatus.EXPRESSED

            [express_name] = [
                e["name"] for e in config.EXPRESS_LIST if e["id"] == courier
            ]

            express_info = [
                dict(
                    express_number=courier_number,
                    express_name=express_name,
                    express_symbol=courier,
                )
            ]

            # 发货时调用确认发货接口，7天后自动确认收货
            if not add_mq_task(
                order_id,
                message_type=4,
                delay=config.DAYS_AFTER_SHIPPED_FOR_AUTO_COMPLETION * 24 * 3600,
            ):
                logger.error(f"发货失败 order_id={order_id}")
                return self.write(ret_msg(code=-1, error_message=f"更新发货信息失败，请稍后再试。"))

            if isinstance(express_info, list):
                order.sdef_order_express_no = json.dumps(express_info)
            if remarks:
                if order.sdef_order_remarks:
                    order.sdef_order_remarks += remarks
                else:
                    order.sdef_order_remarks = remarks
            session.commit()
        elif action == "update_dn":
            # 快递/物流配送
            if order.sdef_order_status != OrderStatus.EXPRESSED:
                session.close()
                return self.write(ret_msg(code=-1, error_message="非已发货订单，请刷新页面！"))

            [express_name] = [
                e["name"] for e in config.EXPRESS_LIST if e["id"] == courier
            ]

            express_info = [
                dict(
                    express_number=courier_number,
                    express_name=express_name,
                    express_symbol=courier,
                )
            ]

            # 发货时调用确认发货接口，7天后自动确认收货
            if not add_mq_task(
                order_id,
                message_type=4,
                delay=config.DAYS_AFTER_SHIPPED_FOR_AUTO_COMPLETION * 24 * 3600,
            ):
                logger.error(f"发货失败 order_id={order_id}")
                return self.write(ret_msg(code=-1, error_message=f"更新发货信息失败，请稍后再试。"))

            if isinstance(express_info, list):
                order.sdef_order_express_no = json.dumps(express_info)
            if remarks:
                if order.sdef_order_remarks:
                    order.sdef_order_remarks += remarks
                else:
                    order.sdef_order_remarks = remarks
            session.commit()
        elif action == "refund":
            clerk = (
                session.query(Agency)
                .filter_by(ebf_agency_id=agency_id, ebf_agency_sub_type=1)
                .first()
            )
            if not (flag or clerk):
                session.close()
                return self.write(ret_msg(code=-1, error_message="只有商家或店长才能确认退款！"))

            if order.sdef_order_status != OrderStatus.CHECK:
                session.close()
                return self.write(ret_msg(code=-1, error_message="顾客申请退款之后才能退款！"))

            cancel_order_immediate_refund(order_id)
        elif action == "confirm":
            if order.sdef_order_status != OrderStatus.EXPRESSED:
                session.close()
                return self.write(ret_msg(code=-1, error_message="只有配送中的订单才能确认送达！"))

            if order.sdef_order_pay_type == PayType.COUPON:
                order.sdef_order_status = OrderStatus.COMPLETE
            else:
                if not add_mq_task(order_id, message_type=6, delay=8 * 3600):
                    logger.info(f"添加自动确认收货到任务队列失败:order_id={order_id}")
                    session.close()
                    return self.finish(ret_msg(-1, error_message="确认送达失败"))
                order.sdef_order_status = OrderStatus.RECEIVED
            session.commit()

        session.close()
        return self.write(ret_msg())


class OrderNumbers(ApiBaseHandler):
    async def get(self):
        """
        获取订单状态分类数
        """
        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        agency_uid = self.get_agency_uid(open_id)
        supplier_id = UserHelper.get_supplier_id(agency_uid)
        is_supplier = UserHelper.is_supplier_staff(agency_uid)

        class GoodsOrder(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "sdet_order", "model": GoodsOrder},
            ]
        )
        filters = dict(
            sdef_order_is_delete=0,
            sdef_order_factory_uid=config.FACTORY_UID,
        )

        if is_supplier and supplier_id:
            # 供应商和职员
            filters["sdef_order_supplier_id"] = supplier_id
        elif store_id:
            # 门店和店员
            filters["sdef_order_store_id"] = store_id
        else:
            # 其他合伙人只看自己的订单
            filters["sdef_order_device_id"] = open_id

        # 待支付订单数
        wait_pay = (
            session.query(GoodsOrder)
            .filter_by(**filters)
            .filter_by(sdef_order_status=OrderStatus.WAIT_PAY)
            .count()
        )

        # 待发货订单数
        wait_express = (
            session.query(GoodsOrder)
            .filter_by(**filters)
            .filter_by(sdef_order_status=OrderStatus.WAIT_EXPRESS)
            .count()
        )

        # 待提货订单数
        wait_pickup = (
            session.query(GoodsOrder)
            .filter_by(**filters)
            .filter_by(sdef_order_status=OrderStatus.WAIT_PICKUP)
            .count()
        )

        # 待收货订单数
        expressed = (
            session.query(GoodsOrder)
            .filter_by(**filters)
            .filter_by(sdef_order_status=OrderStatus.EXPRESSED)
            .count()
        )

        # 已收货订单数
        received = (
            session.query(GoodsOrder)
            .filter_by(**filters)
            .filter_by(sdef_order_status=OrderStatus.RECEIVED)
            .count()
        )

        # 已退款订单数
        refund = (
            session.query(GoodsOrder)
            .filter_by(**filters)
            .filter_by(sdef_order_status=OrderStatus.REFUND)
            .count()
        )

        # 待审核订单数
        check = (
            session.query(GoodsOrder)
            .filter_by(**filters)
            .filter_by(sdef_order_status=OrderStatus.CHECK)
            .count()
        )

        # 售后订单数
        after_sale = (
            session.query(GoodsOrder)
            .filter_by(**filters)
            .filter_by(sdef_order_status=OrderStatus.AFTER_SALE)
            .count()
        )

        # 已完成订单数
        completed = (
            session.query(GoodsOrder)
            .filter_by(**filters)
            .filter_by(sdef_order_status=OrderStatus.COMPLETE)
            .count()
        )

        # 全部订单数
        total = (
            wait_pay
            + wait_express
            + wait_pickup
            + expressed
            + received
            + refund
            + check
            + after_sale
            + completed
        )

        data = {
            "wait_pay": wait_pay,
            "wait_express": wait_express,
            "wait_pickup": wait_pickup,
            "expressed": expressed,
            "received": received,
            "refund": refund,
            "check": check,
            "after_sale": after_sale,
            "completed": completed,
            "total": total,
        }

        session.close()
        return self.finish(ret_msg(data=data))


class EstimateBenefit(ApiBaseHandler):
    async def get(self):
        open_id = await self.get_open_id()
        page_index = int(self.get_parameter("page_index", 0))
        page_size = int(self.get_parameter("page_size", 10))
        ApiHelper.inspect_common_params(page_index, page_size)
        page_start = page_index * page_size
        agency_uid = self.get_agency_uid(open_id)
        agency_id, store_id = self.store_agency_id(open_id)
        supplier_id = UserHelper.get_supplier_id(agency_uid)
        is_supplier = UserHelper.is_supplier_staff(agency_uid)
        status = 0
        today = datetime.date.today()
        year = today.year
        month = today.month
        day = today.day

        target_agency_uid = agency_uid
        # 供应商销售跟单（店长）可以查看供应商总账号分润信息
        agency = UserHelper.get_agency(agency_uid)
        if not agency:
            logger.error(f"账号不存在！agency_id={agency_id} open_id={open_id}")
            return self.write(ret_msg(code=-1, error_message="商家账号不存在！"))
        agency_type = agency.ebf_agency_type
        agency_sub_type = agency.ebf_agency_sub_type
        if is_supplier and agency_type == AgencyType.CLERK and agency_sub_type == 1:
            target_agency_uid = UserHelper.get_agency_uid(supplier_id)

        filters = dict(
            factory_uid=config.FACTORY_UID,
            agency_uid=target_agency_uid,
            status=status,
            is_valid=1,
            is_finish=0,
        )

        class GoodsOrder(object):
            pass

        class Benefit(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "sdet_order", "model": GoodsOrder},
                {"db_table": "sdet_benefit", "model": Benefit},
            ]
        )

        result = (
            session.query(
                func.date_format(Benefit.create_time, "%Y-%m-%d").label("date"),
                func.sum(Benefit.fee).label("fee"),
            )
            .filter_by(**filters)
            .group_by("date")
            .order_by(desc("date"))[page_start : page_start + page_size]
        )

        today_fee = (
            session.query(func.sum(Benefit.fee))
            .filter_by(agency_uid=agency_uid, is_valid=1)
            .filter(
                and_(
                    extract("year", Benefit.create_time) == year,
                    extract("month", Benefit.create_time) == month,
                    extract("day", Benefit.create_time) == day,
                )
            )
            .scalar()
        )

        filter2 = dict(
            sdef_order_is_delete=0,
            sdef_order_factory_uid=config.FACTORY_UID,
            sdef_order_pay_status=1,
        )
        if supplier_id and is_supplier:
            filter2["sdef_order_supplier_id"] = supplier_id
        elif store_id:
            filter2["sdef_order_store_id"] = store_id
        else:
            return self.write(ret_msg(code=-1, error_message="商家或店员账号错误！"))

        order_nums = (
            session.query(func.count(GoodsOrder.sdef_order_id))
            .filter_by(**filter2)
            .filter(
                and_(
                    extract("year", GoodsOrder.sdef_order_create_time) == year,
                    extract("month", GoodsOrder.sdef_order_create_time) == month,
                    extract("day", GoodsOrder.sdef_order_create_time) == day,
                )
            )
            .scalar()
        )

        benefits = []
        now = today.strftime("%Y-%m-%d")
        for b in result:
            benefit = dict(
                date=b.date if b.date != now else "今日收入",
                fee="%.2f" % b.fee,
                status=status,
            )
            benefits.append(benefit)

        context = dict(
            benefits=benefits,
            today_fee="%.2f" % today_fee if today_fee else "0.00",
            order_nums=order_nums,
        )
        session.close()
        return self.write(ret_msg(data=context))


class ManageGoods(ApiBaseHandler):
    async def get(self):
        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        if not agency_id or not store_id:
            return self.write(ret_msg(code=-1, error_message="商家或店员账号错误！"))

        page_index = int(self.get_parameter("page_index", 0))
        page_size = int(self.get_parameter("page_size", 10))
        ApiHelper.inspect_common_params(page_index, page_size)
        page_start = page_index * page_size

        class Goods(object):
            pass

        class GoodsOrder(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "sdet_store_goods", "model": Goods},
                {"db_table": "sdet_order", "model": GoodsOrder},
            ]
        )

        filter = dict(
            sdef_goods_is_delete=0,
            sdef_goods_store_id=store_id,
            sdef_goods_factory_uid=config.FACTORY_UID,
        )
        filter2 = dict(
            sdef_order_is_delete=0,
            sdef_order_factory_uid=config.FACTORY_UID,
            sdef_order_type=OrderType.NORMAL,
            sdef_order_pay_status=PayStatus.SUCCESS,
            sdef_order_store_id=store_id,
        )
        goods_array = (
            session.query(Goods)
            .filter_by(**filter)
            .order_by(Goods.sdef_goods_order_num.asc(), Goods.sdef_goods_price.asc())[
                page_start : page_start + page_size
            ]
        )

        now = datetime.datetime.now()
        date_start = (now + datetime.timedelta(days=-30)).replace(
            hour=0, minute=0, second=0
        )
        date_end = now
        order_array = (
            session.query(GoodsOrder)
            .filter_by(**filter2)
            .filter(GoodsOrder.sdef_order_create_time >= date_start)
            .filter(GoodsOrder.sdef_order_create_time <= date_end)
            .order_by(GoodsOrder.sdef_order_id.desc())
            .all()
        )

        goods_list = []
        for g in goods_array:
            goods = {}
            id = g.sdef_goods_id
            goods["id"] = id
            goods["goods_thumbnail"] = json.loads(g.sdef_goods_thumbnail)
            goods["goods_name"] = g.sdef_goods_name
            goods["goods_price"] = str(g.sdef_goods_price.quantize(Decimal("0.00")))
            goods["goods_member_price"] = str(
                g.sdef_goods_member_price.quantize(Decimal("0.00"))
            )
            goods["goods_count"] = g.sdef_goods_count
            goods["unit"] = ApiHelper.get_unit(g.sdef_goods_unit)
            goods["sdef_goods_status"] = g.sdef_goods_status
            month_sale = 0
            for o in order_array:
                cart_goods = json.loads(o.sdef_order_goods)
                for c in cart_goods:
                    if c["id"] == id:
                        month_sale += c["count"]

            goods["month_sale"] = month_sale
            goods_list.append(goods)

        context = dict(
            goods_list=goods_list,
            is_membership=self.is_membership(open_id),
            store_id=store_id,
        )

        session.close()
        return self.write(ret_msg(data=context))

    async def post(self):
        goods_id = self.get_parameter("id", None)
        if not goods_id:
            return self.write(ret_msg(code=-1, error_message="缺少参数商品编号！"))

        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        if not agency_id or not store_id:
            return self.write(ret_msg(code=-1, error_message="商家或店员账号错误！"))

        class Agency(object):
            pass

        class Goods(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "ebt_agency", "model": Agency},
                {"db_table": "sdet_store_goods", "model": Goods},
            ]
        )

        filter = dict(
            sdef_goods_id=goods_id,
            sdef_goods_is_delete=0,
            sdef_goods_store_id=store_id,
            sdef_goods_factory_uid=config.FACTORY_UID,
        )
        goods = session.query(Goods).filter_by(**filter).first()
        agency = session.query(Agency).filter_by(ebf_agency_id=store_id).first()
        if not goods:
            session.close()
            return self.write(ret_msg(code=-1, error_message="商品不存在！"))

        count = goods.sdef_goods_count
        goods_name = goods.sdef_goods_name
        store_name = agency.ebf_agency_name
        first = "您好，门店有件商品库存不足申请增加库存！"
        touser = "o7qyl0gq4IcXK5oa7aIYWqke0LAs"
        tasks.send_add_stock_notice.delay(
            first, touser, store_name, goods_name, count, store_id
        )
        session.close()
        return self.write(ret_msg())


class StoreAccount(ApiBaseHandler):
    async def get(self):
        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        agency_uid = self.get_agency_uid(open_id)
        if agency_id and store_id:
            if agency_id != store_id:
                logger.error(
                    f"StoreAccount: 商家账号错误！open_id={open_id} store_id={store_id} agency_id={agency_id}"
                )
                return self.write(ret_msg(code=-1, error_message="商家账号错误！"))
        else:
            supplier_id = UserHelper.get_supplier_id(agency_uid)
            is_supplier = UserHelper.is_supplier_staff(agency_uid)
            if supplier_id and is_supplier:
                store_id = supplier_id
            else:
                logger.error(
                    f"StoreAccount: 商家账号错误！open_id={open_id} supplier_id={supplier_id}"
                )
                return self.write(ret_msg(code=-1, error_message="商家账号错误！"))

        class User(object):
            pass

        class Agency(object):
            pass

        class UserAgency(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "ebt_user", "model": User},
                {"db_table": "ebt_agency", "model": Agency},
                {"db_table": "ebt_user_agency", "model": UserAgency},
            ]
        )

        agency = session.query(Agency).filter_by(ebf_agency_id=store_id).first()
        default_time = {
            "day": [1, 2, 3, 4, 5, 6, 7],
            "am": "00:00-14:00",
            "pm": "14:00-24:00",
        }
        work_time = (
            json.loads(agency.ebf_agency_work_time)
            if agency.ebf_agency_work_time
            else default_time
        )
        work_switch = agency.ebf_agency_is_active
        is_work = ApiHelper.check_is_work_time(work_time, work_switch)
        headurl = self.get_store_logo(store_id, agency)
        sales_rate = agency.ebf_agency_sales_rate
        context = dict(
            headurl=headurl,
            store_id=store_id,
            store_name=agency.ebf_agency_name,
            store_address=agency.ebf_agency_address,
            phone=agency.ebf_agency_contact,
            work_time=work_time,
            is_work=is_work,
            sales_rate=sales_rate,
        )
        session.close()
        return self.write(ret_msg(data=context))

    async def post(self):
        action = self.get_parameter("action", None)
        is_work = self.get_parameter("is_work", None)
        headimg = self.request.files.get("headimg", None)
        name = self.get_parameter("name", None)
        phone = self.get_parameter("phone", None)
        worktime = self.get_parameter("worktime", None)
        address = self.get_parameter("address", None)
        lat = self.get_parameter("lat", None)
        lng = self.get_parameter("lng", None)
        sales_rate = float(self.get_parameter("sales_rate", 0.3))

        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        if not agency_id or not store_id:
            return self.write(ret_msg(code=-1, error_message="商家账号错误！"))

        if agency_id != store_id:
            return self.write(ret_msg(code=-1, error_message="商家账号错误！"))

        if action is None:
            return self.write(ret_msg(code=-1, error_message="请求参数错误！"))

        class Agency(object):
            pass

        class User(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "ebt_agency", "model": Agency},
                {"db_table": "ebt_user", "model": User},
            ]
        )

        agency = session.query(Agency).filter_by(ebf_agency_id=store_id).first()
        if action == "set_work":
            if is_work is None:
                session.close()
                return self.write(ret_msg(code=-1, error_message="请求参数错误！"))

            is_work = int(is_work)
            worked = agency.ebf_agency_is_active
            work_time = json.loads(agency.ebf_agency_work_time)
            working = ApiHelper.check_is_work_time(work_time, worked)
            if worked == 1 and working == 0 and is_work == 1:
                session.close()
                return self.write(
                    ret_msg(code=-1, error_message="现在是打烊时间,如需开启营业,请调整营业时间！")
                )

            agency.ebf_agency_is_active = is_work
        elif action == "update_headimg" or action == "updateheadimg":
            logger.info("action=%s, open_id=%s" % (action, open_id))
            size = int(self.request.headers.get("Content-Length")) / 1024

            if size > 2000:
                session.close()
                return self.write(ret_msg(code=-1, error_message="上传文件不能大于2M！"))

            if not headimg:
                session.close()
                return self.write(ret_msg(code=-1, error_message="请选择要上传的图片！"))

            img = headimg[0]
            secret_id = config.COS_APP_SECRET_ID
            secret_key = config.COS_APP_SECRET_KEY
            region = "ap-guangzhou"
            token = ""
            scheme = "https"

            try:
                cfg = CosConfig(
                    Region=region,
                    Secret_id=secret_id,
                    Secret_key=secret_key,
                    Token=token,
                    Scheme=scheme,
                )
                client = CosS3Client(cfg)
                base_url = (
                    "https://"
                    + "style-1251902022."
                    + "file.myqcloud.com/static/headimg/"
                )
                i = img["filename"].rfind(".") + 1
                filename = generator_trade_no() + "." + img["filename"][i:]
                response = client.put_object(
                    Bucket=config.COS_BUCKET + "-" + config.COS_APP_ID,
                    Body=img["body"],
                    Key="static/headimg/" + filename,
                )
            except Exception as e:
                logger.error("图片上传失败： %s" % e)
                session.close()
                return self.write(ret_msg(code=-1, error_message="图片上传失败！"))

            logger.debug(response)
            headurl = base_url + filename
            user_id1 = "P" + str(agency_id)
            user_id2 = (
                ("P" + agency.ebf_agency_contact) if agency.ebf_agency_contact else None
            )
            user_id3 = agency.ebf_agency_contact if agency.ebf_agency_contact else None
            id_list = [user_id1, user_id2, user_id3]
            user = (
                session.query(User)
                .filter(User.ebf_user_id.in_(id_list))
                .order_by(User.ebf_user_create_date.desc())
                .first()
            )
            if not user:
                session.close()
                return self.write(ret_msg(code=-1, error_message="用户表无记录！"))

            user.ebf_user_headurl = headurl
            logger.info("headurl=%s" % headurl)
        elif action == "update_name":
            if name is None:
                session.close()
                return self.write(ret_msg(code=-1, error_message="门店名字不能为空！"))

            agency.ebf_agency_name = name
        elif action == "update_phone":
            if phone is None:
                session.close()
                return self.write(ret_msg(code=-1, error_message="门店电话不能为空！"))

            agency.ebf_agency_contact = phone
        elif action == "update_worktime":
            if worktime is None:
                session.close()
                return self.write(ret_msg(code=-1, error_message="门店营业时间为空！"))

            agency.ebf_agency_work_time = json.dumps(worktime)
        elif action == "update_address":
            if address is None or lat is None or lng is None:
                session.close()
                return self.write(ret_msg(code=-1, error_message="门店地址和经纬度不能为空！"))

            agency.ebf_agency_address = address
            agency.ebf_agency_latitude = lat
            agency.ebf_agency_longitude = lng
        elif action == "update_sales_rate":
            if not(0.0 <= sales_rate <= 1.0):
                session.close()
                return self.write(ret_msg(code=-1, error_message=f"业务员分成比率错误: {sales_rate} (正确取值范围 0.0-1.0)"))
            agency.ebf_agency_sales_rate = sales_rate
        else:
            pass

        session.commit()
        session.close()
        return self.write(ret_msg())


class Register(ApiBaseHandler):
    def update_user_uid(self, open_id, agency_uid):
        try:

            class User(object):
                pass

            session = self.get_db_session([{"db_table": "ebt_user", "model": User}])

            user = session.query(User).filter_by(ebf_user_id=open_id).first()
            user.ebf_user_agency_uid = agency_uid
            session.commit()
            session.close()
        except Exception as e:
            session.close()
            logger.error("用户注册修改uid失败：%s" % e)

    async def add_agency(
        self,
        type,
        open_id,
        inviter_oid=None,
        name=None,
        address=None,
        phone=None,
        store_id=None,
        clerk=None,
        lat=None,
        lng=None,
    ):
        class User(object):
            pass

        class Agency(object):
            pass

        class UserAgency(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "ebt_user", "model": User},
                {"db_table": "ebt_agency", "model": Agency},
                {"db_table": "ebt_user_agency", "model": UserAgency},
            ]
        )

        ua = session.query(UserAgency).filter_by(ebf_ua_bind_user_id=open_id).first()
        if ua:
            session.close()
            return self.write(ret_msg(code=-1, error_message="已经注册成功，不能重复注册"))

        redis = redis_util.client
        flag = redis.get(f"register_{open_id}")
        if flag:
            session.close()
            return self.write(ret_msg(code=-1, error_message="不能重复请求"))
        else:
            redis.setex(f"register_{open_id}", 60, 1)
        password = "style999"
        md5_obj = md5()
        md5_obj.update(password.encode("utf-8"))
        pwd = md5_obj.hexdigest()
        logo_url = f"https://{DOMAIN}/static/img/content/logo-60x60.png"
        agency_uid = str(uuid.uuid1())
        user = session.query(User).filter_by(ebf_user_id=open_id).first()
        flag = False

        if type == AgencyType.CLERK:
            # 注册店员
            store = session.query(Agency).filter_by(ebf_agency_id=store_id).first()
            uid = store.ebf_agency_uid
            store_ua = (
                session.query(UserAgency).filter_by(ebf_agency_id=store_id).first()
            )
            store_user_id = store_ua.ebf_ua_bind_user_id
            if not user:
                logger.info("创建用户：open_id=%s" % open_id)
                flag = True
                user = await self.create_user(open_id, uid, store_user_id)

            parent_agency_id = store_id
            depth = store.ebf_agency_depth + 1
            career_agency = UserHelper.get_career_agency(uid)
            career_agency_uid = (
                career_agency.ebf_agency_uid
                if career_agency
                else config.DEFAULT_AGENCY_UID
            )
        else:
            # 注册商家
            invite_user = session.query(User).filter_by(ebf_user_id=inviter_oid).first()
            if not invite_user:
                logger.error("邀请人不存在: oid=%s, inviter_oid=%s" % (open_id, inviter_oid))
                session.close()
                return self.write(ret_msg(code=-1, error_message="邀请人不存在！"))

            uid = invite_user.ebf_user_agency_uid
            if not user:
                logger.info("创建用户：open_id=%s" % open_id)
                flag = True
                user = await self.create_user(open_id, uid, inviter_oid)

            if (
                user.ebf_user_agency_uid == config.DEFAULT_AGENCY_UID
                and uid != config.DEFAULT_AGENCY_UID
            ):
                parent_uid = uid
            else:
                parent_uid = user.ebf_user_agency_uid

            if type == AgencyType.STORE:
                work_time = {
                    "day": [1, 2, 3, 4, 5, 6, 7],
                    "am": "00:00-14:00",
                    "pm": "14:00-24:00",
                }
                work_time = json.dumps(work_time)

            parent_agency = (
                session.query(Agency).filter_by(ebf_agency_uid=parent_uid).first()
            )
            parent_agency_id = (
                parent_agency.ebf_agency_id
                if parent_agency
                else config.DEFAULT_AGENCY_ID
            )
            depth = parent_agency.ebf_agency_depth + 1 if parent_agency else 2
            career_agency = UserHelper.get_career_agency(parent_uid)
            career_agency_uid = (
                career_agency.ebf_agency_uid
                if career_agency
                else config.DEFAULT_AGENCY_UID
            )
            logger.info("parent_uid=%s, oid=%s" % (user.ebf_user_agency_uid, open_id))

        try:
            _agency = Agency()
            _agency.ebf_agency_name = name
            _agency.ebf_agency_uid = agency_uid
            _agency.ebf_agency_contact = phone
            _agency.ebf_factory_id = config.FACTORY_ID
            _agency.ebf_agency_parent_id = parent_agency_id
            _agency.ebf_agency_career_uid = career_agency_uid
            _agency.ebf_agency_invite_uid = uid
            _agency.ebf_agency_depth = depth
            _agency.ebf_agency_create_time = datetime.datetime.now()
            _agency.ebf_agency_type = type
            _agency.ebf_agency_address = address
            _agency.ebf_agency_latitude = lat
            _agency.ebf_agency_longitude = lng
            if type == AgencyType.CLERK and not clerk:
                # _agency.ebf_agency_sub_type = 1 # 默认第一个店员为店长
                pass
            elif type == AgencyType.STORE:
                _agency.ebf_agency_work_time = work_time
                _agency.ebf_agency_is_active = 1
                _agency.ebf_agency_sub_type = 0
            elif type == AgencyType.SALES and address:
                _agency.ebf_agency_sub_type = 3
                _agency.ebf_agency_remarks = "酒卡发卡人"
            elif type == AgencyType.SALES:
                _agency.ebf_agency_sub_type = 0
            session.add(_agency)
            session.flush()

            agency_id = _agency.ebf_agency_id
            id_str = str(agency_id)

            if not name:
                _agency.ebf_agency_name = id_str
            new_user = User()
            new_user.ebf_user_id = "P" + id_str
            new_user.ebf_user_password = pwd
            new_user.user_create_date = datetime.datetime.utcnow()
            new_user.ebf_user_phone = phone
            new_user.ebf_user_nickname = user.ebf_user_nickname
            new_user.ebf_user_factory_id = config.FACTORY_ID
            new_user.ebf_user_type = 3
            new_user.ebf_user_gender = user.ebf_user_gender
            new_user.ebf_user_agency_uid = agency_uid
            user.ebf_user_agency_uid = agency_uid
            if type == AgencyType.STORE:
                new_user.ebf_user_headurl = logo_url

            user.ebf_user_agency_uid = agency_uid
            user.ebf_user_phone = phone
            session.add(new_user)
            session.flush()

            _user_agency = UserAgency()
            _user_agency.ebf_user_id = "P" + id_str
            _user_agency.ebf_agency_id = agency_id
            _user_agency.ebf_ua_bind_user_id = open_id
            session.add(_user_agency)
        except Exception as e:
            logger.error(e)
            session.rollback()
            session.close()
            if type == AgencyType.CLERK:
                url = "/static/storebackstage/index.html#/registerFail"
                return self.redirect(url)
            else:
                return self.write(ret_msg(code=-1, error_message="注册失败,请重试"))

        session.commit()
        session.close()
        if flag:
            self.update_user_uid(open_id, agency_uid)

        if type == AgencyType.CLERK:
            # 店员注册
            logger.info(f"店员注册: agency_id={agency_id}")
            url = "/static/storebackstage/index.html#/registerSuccess"
            return self.redirect(url)
        elif type == AgencyType.STORE:
            # 触发商家注册异步事件
            logger.info(f"商家注册: agency_id={agency_id}")
            tasks.store_registered.delay(agency_id)
            return self.write(ret_msg())
        else:
            # 触发引荐人注册异步事件
            logger.info(f"新合伙人注册: agency_id={agency_id}")
            tasks.agency_registered.delay(agency_id)
            return self.write(ret_msg())

    async def get(self):
        store_id = self.get_parameter("store_id", None)
        type = int(self.get_parameter("type", 0))
        if not all([store_id, type]):
            return self.write(ret_msg(code=-1, error_message="缺少请求参数门店编号或注册类型！"))

        if type != AgencyType.CLERK:
            return self.write(ret_msg(code=-1, error_message="注册类型错误！"))

        class User(object):
            pass

        class Agency(object):
            pass

        class UserAgency(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "ebt_user", "model": User},
                {"db_table": "ebt_agency", "model": Agency},
                {"db_table": "ebt_user_agency", "model": UserAgency},
            ]
        )

        open_id = await self.get_open_id()
        store_id = int(store_id)
        store = session.query(Agency).filter_by(ebf_agency_id=store_id).first()
        if not store:
            session.close()
            logger.error(f"商家不存在：agency_id={store_id}")
            return self.write(ret_msg(code=-1, error_message="商家不存在！"))

        agency_type = store.ebf_agency_type
        if agency_type != AgencyType.STORE and agency_type != AgencyType.SUPPLIER:
            session.close()
            logger.error(f"商家类型错误：agency_id={store_id} agency_type={agency_type}")
            return self.write(ret_msg(code=-1, error_message="商家类型错误！"))

        ua = session.query(UserAgency).filter_by(ebf_ua_bind_user_id=open_id).first()
        clerk = (
            session.query(Agency)
            .filter_by(ebf_agency_parent_id=store_id, ebf_agency_type=AgencyType.CLERK)
            .first()
        )
        if ua:
            # 已有合伙人账户注册店员
            agency_id = ua.ebf_agency_id
            msg = "您已注册，若要修改账户类型为店员，请在微信公众号留言或拨打客服电话人工处理。"
            agency = session.query(Agency).filter_by(ebf_agency_id=agency_id).first()
            if not agency:
                session.close()
                return self.write(ret_msg(code=-1, error_message="账号错误！"))

            if agency.ebf_agency_type:
                # 非初级合伙人
                session.close()
                return self.write(ret_msg(code=-1, error_message=msg))
            else:
                # 初级合伙人
                if store.ebf_agency_parent_id == agency_id:
                    session.close()
                    return self.write(ret_msg(code=-1, error_message="商家上级不能注册相应商家店员！"))

                agency.ebf_agency_type = type
                # agency.ebf_agency_sub_type = 0 if clerk else 1  # 默认第一个店员为店长
                agency.ebf_agency_parent_id = store_id
                agency.ebf_agency_update_time = datetime.datetime.now()
                session.commit()
                session.close()
                url = "/static/storebackstage/index.html#/registerSuccess"
                return self.redirect(url)
        else:
            # 新增店员账户
            await self.add_agency(type, open_id, store_id=store_id, clerk=clerk)

    async def post(self):
        phone = self.get_parameter("phone", None)
        store_name = self.get_parameter("store_name", None)
        name = self.get_parameter("name", None)
        inviter_oid = self.get_parameter("inviter_oid", None)
        address = self.get_parameter("address", None)
        type = int(self.get_parameter("type", 0))  # 3=商家 4=店员 5=推荐人/业务员
        lat = self.get_parameter("lat", None)
        lng = self.get_parameter("lng", None)

        store_id = self.get_parameter("store_id", None)  # 店员注册

        open_id = await self.get_open_id()
        logo_url = f"https://{DOMAIN}/static/img/content/logo-60x60.png"
        logger.info("inviter_oid=%s, oid=%s" % (inviter_oid, open_id))

        if not re.match(r"^1\d{10}$", phone):
            return self.write(ret_msg(code=-1, error_message="手机号格式不正确"))

        if not open_id:
            return self.write(ret_msg(code=-1, error_message="系统繁忙，请稍后重试！"))

        if not type:
            return self.write(ret_msg(code=-1, error_message="缺少请求参数注册类型！"))

        if type == AgencyType.STORE:
            if not all([store_name, address, phone, inviter_oid]):
                return self.write(ret_msg(code=-1, error_message="缺少请求参数！"))

            if not (lat and lng):
                return self.write(ret_msg(code=-1, error_message="缺少参数经纬度！"))

            work_time = {
                "day": [1, 2, 3, 4, 5, 6, 7],
                "am": "00:00-14:00",
                "pm": "14:00-24:00",
            }
            work_time = json.dumps(work_time)
            address = address.replace(" ", "")
        elif type == AgencyType.CLERK:
            if not all([phone, name]):
                return self.write(ret_msg(code=-1, error_message="缺少请求参数！"))
        elif type == AgencyType.SALES:
            if not all([phone, name]):
                return self.write(ret_msg(code=-1, error_message="缺少请求参数！"))
        else:
            return self.write(ret_msg(code=-1, error_message="注册类型错误！"))

        class User(object):
            pass

        class Agency(object):
            pass

        class UserAgency(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "ebt_user", "model": User},
                {"db_table": "ebt_agency", "model": Agency},
                {"db_table": "ebt_user_agency", "model": UserAgency},
            ]
        )

        ua = session.query(UserAgency).filter_by(ebf_ua_bind_user_id=open_id).first()
        if ua:
            agency_id = ua.ebf_agency_id
            agency = session.query(Agency).filter_by(ebf_agency_id=agency_id).first()
            if agency.ebf_agency_type:
                msg = f"您已注册，若要修改账户类型，请在微信公众号留言或拨打客服电话人工处理。"
                session.close()
                return self.write(ret_msg(code=-1, error_message=msg))
            else:
                # 初级合伙人改变新身份
                if type == AgencyType.SALES and address:
                    agency.ebf_agency_type = type
                    agency.ebf_agency_sub_type = 3
                    agency.ebf_agency_update_time = datetime.datetime.now()
                    agency.ebf_agency_name = name
                    agency.ebf_agency_address = address
                    agency.ebf_agency_contact = phone
                    agency.ebf_agency_latitude = lat
                    agency.ebf_agency_longitude = lng
                    session.commit()
                    session.close()
                    tasks.agency_registered(agency_id)
                    return self.write(ret_msg())
                elif type == AgencyType.SALES:
                    agency.ebf_agency_type = type
                    agency.ebf_agency_sub_type = 0
                    agency.ebf_agency_update_time = datetime.datetime.now()
                    agency.ebf_agency_name = name
                    agency.ebf_agency_contact = phone
                    session.commit()
                    session.close()
                    tasks.agency_registered(agency_id)
                    return self.write(ret_msg())
                else:
                    agency.ebf_agency_type = type
                    user_id1 = "P" + str(agency_id)
                    user_id2 = (
                        ("P" + agency.ebf_agency_contact)
                        if agency.ebf_agency_contact
                        else None
                    )
                    user_id3 = (
                        agency.ebf_agency_contact if agency.ebf_agency_contact else None
                    )
                    id_list = [user_id1, user_id2, user_id3]
                    user = (
                        session.query(User)
                        .filter(User.ebf_user_id.in_(id_list))
                        .first()
                    )
                    if user:
                        user.ebf_user_headurl = logo_url
                    agency.ebf_agency_update_time = datetime.datetime.now()
                    agency.ebf_agency_name = store_name
                    agency.ebf_agency_address = address
                    agency.ebf_agency_latitude = lat
                    agency.ebf_agency_longitude = lng
                    agency.ebf_agency_work_time = work_time
                    agency.ebf_agency_contact = phone
                    session.commit()
                    session.close()
                    logger.info(f"初级合伙人账户注册餐厅: agency_id={agency_id}")
                    # 触发餐厅注册异步事件
                    tasks.store_registered.delay(agency_id)
                    return self.write(ret_msg())
        else:
            if type == AgencyType.STORE:
                # 新增门店
                await self.add_agency(
                    type,
                    open_id,
                    inviter_oid=inviter_oid,
                    name=store_name,
                    address=address,
                    phone=phone,
                    lat=lat,
                    lng=lng,
                )
            else:
                # 新增新合伙人/店员/业务员
                await self.add_agency(
                    type,
                    open_id,
                    inviter_oid=inviter_oid,
                    name=name,
                    address=address,
                    phone=phone,
                    store_id=store_id,
                    lat=lat,
                    lng=lng,
                )


class StoreClerk(ApiBaseHandler):
    async def get(self):
        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        agency_uid = self.get_agency_uid(open_id)
        if agency_id and store_id:
            if agency_id != store_id:
                logger.error(
                    f"StoreClerk: agency_id {agency_id} != store_id {store_id}"
                )
                return self.write(ret_msg(code=-1, error_message="不是商家！"))
        else:
            supplier_id = UserHelper.get_supplier_id(agency_uid)
            is_supplier = UserHelper.is_supplier_staff(agency_uid)
            if supplier_id and is_supplier:
                agency_id = supplier_id
            else:
                logger.error(
                    f"StoreClerk: agency_id: {agency_id} store_id: {store_id} supplier_id: {supplier_id} is_supplier: {is_supplier}"
                )
                return self.write(ret_msg(code=-1, error_message="不是商家！"))

        class User(object):
            pass

        class Agency(object):
            pass

        class UserAgency(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "ebt_user", "model": User},
                {"db_table": "ebt_agency", "model": Agency},
                {"db_table": "ebt_user_agency", "model": UserAgency},
            ]
        )

        page_index = int(self.get_parameter("page_index", 0))
        page_size = int(self.get_parameter("page_size", 10))
        ApiHelper.inspect_common_params(page_index, page_size)
        page_start = page_index * page_size
        agency_list = list()
        agencys = (
            session.query(Agency)
            .filter_by(ebf_agency_parent_id=agency_id, ebf_agency_type=4)
            .order_by(Agency.ebf_agency_id.desc())[page_start : page_start + page_size]
        )

        count = (
            session.query(func.count(Agency.ebf_agency_id))
            .filter_by(ebf_agency_parent_id=agency_id, ebf_agency_type=4)
            .scalar()
        )
        for agency in agencys:
            id = agency.ebf_agency_id
            ua = session.query(UserAgency).filter_by(ebf_agency_id=id).first()
            if not ua:
                continue

            user_id = ua.ebf_ua_bind_user_id
            user = session.query(User).filter_by(ebf_user_id=user_id).first()
            if not user:
                continue

            create_date = agency.ebf_agency_create_time
            clerk = dict(
                nickname=user.ebf_user_nickname,
                agency_id=id,
                sub_type=agency.ebf_agency_sub_type,
                create_date=create_date.strftime("%Y年%m月%d日") if create_date else None,
            )
            agency_list.append(clerk)

        context = dict(count=count, clerks=agency_list)
        session.close()
        return self.write(ret_msg(data=context))

    async def post(self):
        id = int(self.get_parameter("agency_id", 0))
        if not id:
            return self.write(ret_msg(code=-1, error_message="请求参数错误！"))

        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        if not agency_id or not store_id:
            return self.write(ret_msg(code=-1, error_message="商家账号错误！"))

        if agency_id != store_id:
            return self.write(ret_msg(code=-1, error_message="不是商家！"))

        class Agency(object):
            pass

        session = self.get_db_session([{"db_table": "ebt_agency", "model": Agency}])

        agency = (
            session.query(Agency)
            .filter_by(ebf_agency_id=id, ebf_agency_parent_id=store_id)
            .first()
        )
        if not agency:
            session.close()
            return self.write(ret_msg(code=-1, error_message="店员编号错误！"))

        agency.ebf_agency_parent_id = config.DEFAULT_AGENCY_ID
        agency.ebf_agency_update_time = datetime.datetime.now()
        session.commit()
        session.close()
        return self.write(ret_msg())


class PrinterSetup(ApiBaseHandler):
    async def get(self):
        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        if not agency_id or not store_id:
            return self.write(ret_msg(code=-1, error_message="商家账号错误！"))

        if agency_id != store_id:
            return self.write(ret_msg(code=-1, error_message="不是商家！"))

        class Printer(object):
            pass

        session = self.get_db_session(
            [{"db_table": "sdet_store_printer", "model": Printer}]
        )

        printer = session.query(Printer).filter_by(ebf_store_id=store_id).first()
        if not printer:
            data = dict()
        else:
            data = dict(
                printer_name=printer.ebf_printer_name,
                printer_type=printer.ebf_printer_type,
                serial_number=printer.ebf_printer_serial_number,
                times=printer.ebf_printer_copies,
                status=printer.ebf_printer_status,
            )

        return self.write(ret_msg(data=data))

    async def post(self):
        action = self.get_parameter("action", None)
        serial_number = self.get_parameter("serial_number", None)
        times = self.get_parameter("times", None)
        printer_name = self.get_parameter("printer_name", None)
        status = int(self.get_parameter("status", 0))
        if not action:
            return self.write(ret_msg(code=-1, error_message="请求参数错误！"))

        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        if not agency_id or not store_id:
            return self.write(ret_msg(code=-1, error_message="商家账号错误！"))

        if agency_id != store_id:
            return self.write(ret_msg(code=-1, error_message="不是商家！"))

        class Printer(object):
            pass

        class Agency(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "ebt_agency", "model": Agency},
                {"db_table": "sdet_store_printer", "model": Printer},
            ]
        )

        printer = session.query(Printer).filter_by(ebf_store_id=store_id).first()
        if not printer:
            if action != "add":
                session.close()
                return self.write(ret_msg(code=-1, error_message="本店还没有添加打印机！"))
            else:
                if not serial_number:
                    session.close()
                    return self.write(ret_msg(code=-1, error_message="缺少参数打印机编号！"))

                p = Printer()
                p.ebf_printer_name = "飞鹅打印机"
                p.ebf_store_id = store_id
                p.ebf_printer_serial_number = serial_number
                p.ebf_printer_scene = "门店订单"
                p.ebf_printer_play_type = "PAID"
                p.ebf_printer_create_time = datetime.datetime.now()
                session.add(p)
                session.commit()
                session.close()
                return self.write(ret_msg())

        if action == "update_id":
            if not serial_number:
                session.close()
                return self.write(ret_msg(code=-1, error_message="缺少参数打印机编号！"))

            printer.ebf_printer_serial_number = serial_number
        elif action == "update_times":
            if not times:
                session.close()
                return self.write(ret_msg(code=-1, error_message="缺少参数打印联数！"))

            printer.ebf_printer_copies = int(times)
        elif action == "update_name":
            if not printer_name:
                session.close()
                return self.write(ret_msg(code=-1, error_message="缺少参数打印机名称！"))

            printer.ebf_printer_name = printer_name
        elif action == "update_status":
            if not status:
                session.close()
                return self.write(ret_msg(code=-1, error_message="缺少参数打印机状态！"))

            printer.ebf_printer_status = status
        else:
            pass

        printer.ebf_printer_update_time = datetime.datetime.now()
        session.commit()
        session.close()
        return self.write(ret_msg())


class PrinterTest(ApiBaseHandler):
    async def get(self):
        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        if not agency_id or not store_id:
            return self.write(ret_msg(code=-1, error_message="商家账号错误！"))

        if agency_id != store_id:
            return self.write(ret_msg(code=-1, error_message="不是商家！"))

        class Printer(object):
            pass

        session = self.get_db_session(
            [{"db_table": "sdet_store_printer", "model": Printer}]
        )

        printer = session.query(Printer).filter_by(ebf_store_id=store_id).first()
        if not printer:
            session.close()
            return self.write(ret_msg(code=-1, error_message="本店还没有添加打印机！"))

        if printer.ebf_printer_status != 1:
            session.close()
            return self.write(ret_msg(code=-1, error_message="打印机已禁止使用！"))

        sn = printer.ebf_printer_serial_number
        times = str(printer.ebf_printer_copies)
        content = None
        data = printOrder(sn, content, times)
        session.close()
        if data:
            logger.info("response=%s" % data)
            if data["ret"] == 0:
                return self.write(ret_msg(data=data["msg"]))
            else:
                return self.write(ret_msg(code=-1, error_message=data["msg"]))
        else:
            logger.error("打印测试失败")
            return self.write(ret_msg(code=-1, error_message="打印测试失败！"))


class SetClerk(ApiBaseHandler):
    async def post(self):
        id = int(self.get_parameter("agency_id", 0))
        action = self.get_parameter("action", None)
        if not id:
            return self.write(ret_msg(code=-1, error_message="请求参数错误！"))

        open_id = await self.get_open_id()
        agency_id, store_id = self.store_agency_id(open_id)
        if not agency_id or not store_id:
            return self.write(ret_msg(code=-1, error_message="商家账号错误！"))

        if agency_id != store_id:
            return self.write(ret_msg(code=-1, error_message="不是商家！"))

        class Agency(object):
            pass

        session = self.get_db_session([{"db_table": "ebt_agency", "model": Agency}])

        agency = (
            session.query(Agency)
            .filter_by(ebf_agency_id=id, ebf_agency_parent_id=store_id)
            .first()
        )
        if not agency:
            session.close()
            return self.write(ret_msg(code=-1, error_message="店员编号错误！"))

        if action == "cancel":
            if agency.ebf_agency_sub_type != 1:
                session.close()
                return self.write(ret_msg(code=-1, error_message="不是店长，无需取消！"))

            agency.ebf_agency_sub_type = 0
        elif action == "setup":
            if agency.ebf_agency_sub_type == 1:
                session.close()
                return self.write(ret_msg(code=-1, error_message="已经是店长，无需设置！"))

            agency.ebf_agency_sub_type = 1
            session.query(Agency).filter_by(
                ebf_agency_parent_id=store_id, ebf_agency_type=AgencyType.CLERK
            ).filter(Agency.ebf_agency_id != id).update({Agency.ebf_agency_sub_type: 0})
        else:
            session.close()
            return self.write(ret_msg(code=-1, error_message="请求参数错误！"))

        agency.ebf_agency_update_time = datetime.datetime.now()
        session.commit()
        session.close()
        return self.write(ret_msg())


class Courier(ApiBaseHandler):
    async def get(self):
        # 快递公司清单
        data = config.EXPRESS_LIST

        return self.write(ret_msg(data=data))

    async def post(self):
        action = self.get_parameter("action", None)
        order_id = self.get_parameter("order_id", None)
        supplier_id = self.get_parameter("supplier_id", None)

        if not (action and order_id and supplier_id):
            return self.write(ret_msg(code=-1, error_message="请求参数错误！"))

        if action != "pickup":
            return self.write(ret_msg(code=-1, error_message="请求参数错误！"))

        # 通知平台发货

        class GoodsOrder(object):
            pass

        class Agency(object):
            pass

        class UserAgency(object):
            pass

        class User(object):
            pass

        class Address(object):
            pass

        session = self.get_db_session(
            [
                {"db_table": "sdet_order", "model": GoodsOrder},
                {"db_table": "ebt_agency", "model": Agency},
                {"db_table": "ebt_user_agency", "model": UserAgency},
                {"db_table": "ebt_user", "model": User},
                {"db_table": "sdet_address", "model": Address},
            ]
        )

        pay = session.query(GoodsOrder).filter_by(sdef_order_id=order_id).first()
        if not pay:
            logger.error(f"发货申请: 订单不存在 order_id={order_id}")
            return self.write(ret_msg(code=-1, error_message="订单不存在！"))

        if pay.sdef_order_pay_status != PayStatus.SUCCESS:
            logger.error(f"发货申请: 订单未支付 order_id={order_id}")
            return self.write(ret_msg(code=-1, error_message="订单未支付！"))

        if pay.sdef_order_status != OrderStatus.WAIT_EXPRESS:
            logger.error(f"发货申请: 非待发货订单 order_id={order_id}")
            return self.write(ret_msg(code=-1, error_message="非待发货订单！"))

        if supplier_id != pay.sdef_order_supplier_id:
            logger.error(f"发货申请: 订单供应商编号对不上！")
            # 需要适配供应商职员
            # return self.write(ret_msg(code=-1, error_message="订单供应商编号对不上！"))

        supplier = session.query(Agency).filter_by(ebf_agency_id=supplier_id).first()
        if not supplier:
            logger.error(f"发货申请: 供应商记录不存在！")
            return self.write(ret_msg(code=-1, error_message="供应商记录不存在！"))

        supplier_name = supplier.ebf_agency_name
        supplier_address = supplier.ebf_agency_address
        supplier_phone = supplier.ebf_agency_contact
        supplier_real_name = supplier.ebf_agency_real_name
        remark = (
            f"提货电话: {supplier_phone} {supplier_real_name}\n提货地址: {supplier_address}\n"
        )

        first = f"【{supplier_name}】申请发货，请尽快通知快递公司提货"

        goods_info = json.loads(pay.sdef_order_goods)
        goods = ""
        for g in goods_info:
            goods_name = g["goods_name"]
            count = Decimal(g["count"])
            goods += f"{goods_name} x {count} \n"

        time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        url = f"https://{DOMAIN}/admin/partner"

        address = ""
        address_id = pay.sdef_order_address_id
        a = session.query(Address).filter_by(sdef_address_id=address_id).first()
        if a:
            address = f"{a.sdef_address_province}{a.sdef_address_city}{a.sdef_address_county}{a.sdef_address_detail} {a.sdef_address_name} {a.sdef_address_phone}"

        # 通知平台发货
        logger.info(
            f"发货申请: 开始通知平台发货 open_id={config.COMMON_NOTICE_RECEIVER} order_id={order_id}"
        )
        tasks.send_new_order_notice.delay(
            config.COMMON_NOTICE_RECEIVER,
            first,
            order_id,
            time,
            goods,
            address,
            remark,
            url,
        )

        # 更新订单状态=待提货
        pay.sdef_order_status = OrderStatus.WAIT_PICKUP
        return self.write(ret_msg())
